﻿using Secs4Net;
using Secs4Net.Sml;
using System.IO;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{

	public partial class Form2 : Form
	{
		SecsGem _secsGem;
		readonly ISecsGemLogger _logger;
		readonly BindingList<PrimaryMessageWrapper> recvBuffer = new BindingList<PrimaryMessageWrapper>();


		class SecsLogger : ISecsGemLogger
		{
			readonly Form2 _form;
			internal SecsLogger(Form2 form)
			{
				_form = form;
			}
			public void MessageIn(SecsMessage msg, int systembyte)
			{
				_form.Invoke((MethodInvoker)delegate {
					_form.richTextBox1.SelectionColor = Color.Black;
					_form.richTextBox1.AppendText($"<-- [0x{systembyte:X8}] {msg.ToSML()}\n");
					//_form.textBox8.Text = msg.RawBytes.Count.ToString();
				});
			}

			public void MessageOut(SecsMessage msg, int systembyte)
			{
				_form.Invoke((MethodInvoker)delegate {
					_form.richTextBox1.SelectionColor = Color.Black;
					_form.richTextBox1.AppendText($"--> [0x{systembyte:X8}] {msg.ToSML()}\n");
				});
			}

			public void Info(string msg)
			{
				_form.Invoke((MethodInvoker)delegate {
					_form.richTextBox1.SelectionColor = Color.Blue;
					_form.richTextBox1.AppendText($"{msg}\n");
				});
			}

			public void Warning(string msg)
			{
				_form.Invoke((MethodInvoker)delegate {
					_form.richTextBox1.SelectionColor = Color.Green;
					_form.richTextBox1.AppendText($"{msg}\n");
				});
			}

			public void Error(string msg, Exception ex = null)
			{
				_form.Invoke((MethodInvoker)delegate {
					_form.richTextBox1.SelectionColor = Color.Red;
					_form.richTextBox1.AppendText($"{msg}\n");
					_form.richTextBox1.SelectionColor = Color.Gray;
					_form.richTextBox1.AppendText($"{ex?.ToString()}\n");
				});
			}

			public void Debug(string msg)
			{
				_form.Invoke((MethodInvoker)delegate {
					_form.richTextBox1.SelectionColor = Color.Yellow;
					_form.richTextBox1.AppendText($"{msg}\n");
				});
			}
		}



		public Form2()
		{
			InitializeComponent();

			radioActiveMode.DataBindings.Add("Enabled", btnEnable, "Enabled");
			radioPassiveMode.DataBindings.Add("Enabled", btnEnable, "Enabled");
			txtAddress.DataBindings.Add("Enabled", btnEnable, "Enabled");
			numPort.DataBindings.Add("Enabled", btnEnable, "Enabled");
			numDeviceId.DataBindings.Add("Enabled", btnEnable, "Enabled");
			numBufferSize.DataBindings.Add("Enabled", btnEnable, "Enabled");
			recvMessageBindingSource.DataSource = recvBuffer;
			Application.ThreadException += (sender, e) => MessageBox.Show(e.Exception.ToString());
			AppDomain.CurrentDomain.UnhandledException += (sender, e) => MessageBox.Show(e.ExceptionObject.ToString());
			_logger = new SecsLogger(this);

		}


		private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
		{
			comboBox_S01.Visible = false;
			comboBox_S02.Visible = false;
			comboBox_S05.Visible = false;
			comboBox_S06.Visible = false;
			comboBox_S07.Visible = false;
			comboBox_S09.Visible = false;
			comboBox_S10.Visible = false;
			comboBox_S12.Visible = false;


			if (comboBox1.SelectedIndex == 1)
			{
				comboBox_S01.Visible = true;
			}
			else if (comboBox1.SelectedIndex == 2)
			{
				comboBox_S02.Visible = true;
			}
			else if (comboBox1.SelectedIndex == 5)
			{
				comboBox_S05.Visible = true;
			}
			else if (comboBox1.SelectedIndex == 6)
			{
				comboBox_S06.Visible = true;
			}
			else if (comboBox1.SelectedIndex == 7)
			{
				comboBox_S07.Visible = true;
			}
			else if (comboBox1.SelectedIndex == 9)
			{
				comboBox_S09.Visible = true;
			}
			else if (comboBox1.SelectedIndex == 10)
			{
				comboBox_S10.Visible = true;
			}
			else if (comboBox1.SelectedIndex == 12)
			{
				comboBox_S12.Visible = true;
			}


		}

		private void comboBox4_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (comboBox4.SelectedIndex != 0) comboBox1.SelectedIndex = 0;
		}

		private void Form1_Load(object sender, EventArgs e)
		{
			comboBox_S02.Left = comboBox_S01.Left; comboBox_S02.Top= comboBox_S01.Top;
		}

		private void btnEnable_Click(object sender, EventArgs e)
		{
			_secsGem?.Dispose();
			_secsGem = new SecsGem(
				radioActiveMode.Checked,
				IPAddress.Parse(txtAddress.Text),
				(int)numPort.Value,
				(int)numBufferSize.Value)
			{ Logger = _logger, DeviceId = (ushort)numDeviceId.Value };

			_secsGem.ConnectionChanged += delegate
			{
				this.Invoke((MethodInvoker)delegate
				{
					lbStatus.Text = _secsGem.State.ToString();
				});
			};

			_secsGem.PrimaryMessageReceived += PrimaryMessageReceived;

			btnEnable.Enabled = false;
			_secsGem.Start();
			btnDisable.Enabled = true;
		}


		private void PrimaryMessageReceived(object sender, PrimaryMessageWrapper e)
		{
			this.Invoke(new MethodInvoker(() => recvBuffer.Add(e)));
		}

		private void btnDisable_Click(object sender, EventArgs e)
		{
			_secsGem?.Dispose();
			_secsGem = null;
			btnEnable.Enabled = true;
			btnDisable.Enabled = false;
			lbStatus.Text = "Disable";
			recvBuffer.Clear();
			richTextBox1.Clear();
		}

		private async void button1_Click(object sender, EventArgs e)
		{
			if (_secsGem.State != ConnectionState.Selected)
				return;
			if (string.IsNullOrWhiteSpace(txtSendPrimary.Text))
				return;

			try
			{
				SecsMessage msg = txtSendPrimary.Text.ToSecsMessage();
				//SecsMessage msg = Secs4Net.Json.JsonExtension.ToSecsMessage(textBox1.Text);
				var reply = await _secsGem.SendAsync(msg);

				txtRecvSecondary.Text = reply.ToSML();

			}
			catch (SecsException ex)
			{
				txtRecvSecondary.Text = ex.Message;
			}
		}

		private void comboBox_S01_SelectedIndexChanged(object sender, EventArgs e)
		{

		}

		private async void button4_Click(object sender, EventArgs e)
		{
			var recv = lstUnreplyMsg.SelectedItem as PrimaryMessageWrapper;
			if (recv == null)
				return;

			if (string.IsNullOrWhiteSpace(txtReplySeconary.Text))
				return;

			await recv.ReplyAsync(txtReplySeconary.Text.ToSecsMessage());
			recvBuffer.Remove(recv);
			txtRecvPrimary.Clear();
			txtReplySeconary.Text = "";
		}

		private void lstUnreplyMsg_SelectedIndexChanged(object sender, EventArgs e)
		{
			var receivedMessage = lstUnreplyMsg.SelectedItem as PrimaryMessageWrapper;

			if(receivedMessage!=null)
			{
				txtRecvPrimary.Text = receivedMessage?.Message.ToSML();

				if (Directory.Exists(@"repSml") == false) Directory.CreateDirectory(@"repSml");
				string patch = @"repSml\s" + receivedMessage.Message.S.ToString() +"f"+ receivedMessage.Message.F.ToString()+".txt";
				if (File.Exists(patch) == true)
				{
					txtReplySeconary.Text = File.ReadAllText(patch);
					if(checkBox1.Checked==true) button4.PerformClick();
				}
				else
				{
					txtReplySeconary.Text = "";
				}
			}

		}

		private void comboBox_S02_SelectedIndexChanged(object sender, EventArgs e)
		{

		}

		private void comboBox_S12_SelectedIndexChanged(object sender, EventArgs e)
		{

		}
		private void comboBox_Sxx_SelectedIndexChanged(object sender, EventArgs e)
		{
			ComboBox commbox = (ComboBox)sender;
			if(commbox.SelectedItem.ToString().Length>8)
			{
				if (Directory.Exists(@"defSml") == false) Directory.CreateDirectory(@"defSml");
				string patch = @"defSml\" + commbox.SelectedItem.ToString().Substring(0, 7) + ".txt";
				if (File.Exists(patch) == true)
				{
					txtSendPrimary.Text = File.ReadAllText(patch);
				}
				else
				{
					txtSendPrimary.Text = "";
				}
			}

		}

	}
}
